#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <thread>
#include <sw/redis++/redis++.h>

using namespace std;
using namespace sw::redis;

// lpush and lrange
void Test1(Redis& redis)
{
    redis.flushall();
    cout << "lpush and lraneg" << endl;

    // 插入单个元素
    redis.lpush("key", "1");

    // 插入一组元素
    redis.lpush("key", {"2", "3", "4", "5"});

    // 插入一组元素，基于迭代器
    vector<string> values = {"6", "7", "8"};
    redis.lpush("key", values.begin(), values.end());

    vector<string> vals;
    auto it = back_inserter(vals);
    redis.lrange("key", 0, -1, it);
    for(auto& e : vals) cout << e << endl;
}

// rpush, lpop and rpop
void Test2(Redis& redis)
{
    redis.flushall();
    cout << "rpush, lpop and rpop" << endl;

    // 插入单个元素
    redis.rpush("key", "1");

    // 插入一组元素
    redis.rpush("key", {"2", "3", "4", "5"});

    // 插入一组元素，基于迭代器
    vector<string> values = {"6", "7", "8"};
    redis.rpush("key", values.begin(), values.end());

    vector<string> vals;
    auto it = back_inserter(vals);
    redis.lrange("key", 0, -1, it);
    for(auto& e : vals) cout << e << " ";
    cout << endl;

    while(1)
    {
        auto ret = redis.lpop("key");
        if(ret)
            cout << "lpop: " << ret.value() << endl;
        else
        {
            cout << "list is empty" << endl;
            break;
        }

        ret = redis.rpop("key");
        if(ret)
            cout << "rpop: " << ret.value() << endl;
        else
        {
            cout << "list is empty" << endl;
            break;
        }
    }
} 

void Test3(Redis& redis)
{
    using namespace std::chrono_literals;
    redis.flushall();
    cout << "blpop and brpop" << endl;

    auto ret = redis.blpop({"key1", "key2", "key3"}, 10s);
    if(ret)
    {
        // OptionalStringPair 中重载了 -> 运算符，故可以使用 ret->first 这样的写法
        cout << "key: " << ret.value().first << endl;
        cout << "element: " << ret.value().second << endl;
    }
    else 
        cout << "ret is invalid" << endl;
}

// llen
void Test4(Redis& redis)
{
    redis.flushall();
    cout << "llen" << endl;

    redis.rpush("key", { "1", "2", "3"});
    long long len = redis.llen("key");
    cout << "len: " << len << endl; 
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    // Test1(redis);
    // Test2(redis);
    // Test3(redis);
    Test4(redis);
    // Test5(redis);
    // Test6(redis);

    return 0;
}